package com.ivo.quartz;

import java.math.BigDecimal;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;
import java.util.HashMap;
import java.util.List;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Repository;
import org.springframework.transaction.annotation.Transactional;

import com.ivo.biz.ActualCapacityOfMon;
import com.ivo.biz.LcmPerformanceManager;
import com.ivo.biz.Performance;
import com.ivo.biz.PerformanceDay;
import com.ivo.biz.PerformanceMon;
import com.ivo.biz.PerformanceService;
import com.ivo.biz.StandardCapacityOfMon;
import com.ivo.core.hibernate.HibernateInvoker;
import com.ivo.sys.Code;
import com.ivo.util.DateUtil;
import com.ivo.util.StringUtil;



@Repository
public class LcmPerformanceQuartz {

	protected Logger logger = LoggerFactory.getLogger(this.getClass());
	
	@Autowired
 	private HibernateInvoker hibernateInvoker;
	 
    @Autowired
    private PerformanceService performanceService;
	
    @Autowired
    private LcmPerformanceManager lcmPerformanceManager;
    
    @Transactional
    @Scheduled(cron = "0 0 9 16 * ? ")//每月16日上午06:00触发
	public void execute() {
    	
		
		SimpleDateFormat sdf =  new SimpleDateFormat("yyyy-MM-dd");
		Calendar calendar = Calendar.getInstance(); 
		
		String str = sdf.format(calendar.getTime());
		String month = str.substring(0, 7);
		//String month ="2018-05";
				
		calendar.add(Calendar.MONTH, -1);       
		String str1 = sdf.format(calendar.getTime());
		String month1 = str1.substring(0, 7);
		
		double attendance = 0.0;
		double totalScore = 0.0;
		double capacity = 0.0;
		double quality = 0.0;
	

		double compatibility = 15.0;
		@SuppressWarnings("unchecked")
		List<PerformanceMon> list = performanceService.listByMonForLcm(month);
		for(PerformanceMon objPerformanceMon:list){
			String emp_id = objPerformanceMon.getEmp_id();
			Performance objPerformanceExist = performanceService.getPerformance(month,emp_id);
			if(objPerformanceExist==null){
				Performance objPerformance =new Performance();
				objPerformance.setMonth(month);
				objPerformance.setFactory(objPerformanceMon.getFactory());
				objPerformance.setEmp_id(objPerformanceMon.getEmp_id());
				objPerformance.setEmp_name(objPerformanceMon.getEmp_name());
				objPerformance.setGender(objPerformanceMon.getGender());
				objPerformance.setOpe_fk(objPerformanceMon.getOpe_fk());
				//logger.info("考勤得分计算start");
				
				attendance = CalculateAttendance(objPerformanceMon,month);
				//logger.info("考勤得分计算end");
				//logger.info("产能得分计算start");
				
				
				if(StringUtil.isEmpty(objPerformanceMon.getClassType())){
					objPerformance.setClassType("");
				}else{
					objPerformance.setClassType(objPerformanceMon.getClassType());
				}
				
				
				
				if(performanceService.getCategory(objPerformanceMon.getOpe_fk()) == (long)24 || performanceService.getCategory(objPerformanceMon.getOpe_fk()) == (long)25){
					if(objPerformanceMon.getOpe_fk() == 195 || objPerformanceMon.getOpe_fk() == 196 || objPerformanceMon.getOpe_fk() == 199 || objPerformanceMon.getOpe_fk() == 200){
						totalScore = 35;
						capacity = CalculateCapacity(objPerformanceMon, totalScore, month);
						totalScore = 30;
						quality = CalculateQuality(objPerformanceMon, totalScore, month);
						totalScore = 10;
						quality = quality + CalculateDPPM(objPerformanceMon, totalScore, month);
					}else{
						totalScore = 25;
						capacity = CalculateCapacity(objPerformanceMon, totalScore, month);
						totalScore = 50;
						quality = CalculateQuality(objPerformanceMon, totalScore, month);
					}
					
					if(quality == 0.0 || attendance == 0.0){
						objPerformance.setAttendance(0.0);
						objPerformance.setCapacity(0.0);
						objPerformance.setSpecialty(0.0);
						objPerformance.setCompatibility(0.0);
					}else{
						objPerformance.setAttendance(attendance);
						objPerformance.setCapacity(capacity);
						objPerformance.setSpecialty(quality);
						objPerformance.setCompatibility(compatibility);
					}
					
				}else{	
					objPerformance.setAttendance(attendance);
					objPerformance.setDiscipline(30.0);
					objPerformance.setCompatibility(30.0);
					objPerformance.setLearns(5.0);
					objPerformance.setProfessional(10.0);
				}
				
				
				
				
				lcmPerformanceManager.save(objPerformance);
			}else{
				if(StringUtil.isEmpty(objPerformanceMon.getClassType())){
					objPerformanceExist.setClassType("");
				}else{
					objPerformanceExist.setClassType(objPerformanceMon.getClassType());
				}
				
				
				
				
				
				lcmPerformanceManager.save(objPerformanceExist);
			}
		
		}
		
		
		logger.info("核算得分结束!");
	}
    
    @Transactional
    @Scheduled(cron = "0 0 10 16 * ? ")
    public void Calculate(){
    	
    	String month = DateUtil.formatDate(new Date()).substring(0, 7);
    	List<Performance> list = hibernateInvoker.find(Performance.class,"from Performance p where p.month = '" + month + "'and p.factory like '%M%' and p.isValid is true");
    	for(Performance p : list){
    		double score = 0.0;
    		if(p.getAttendance() != null){
    			score = score + p.getAttendance();
    		}
    		
    		if(p.getCompatibility() != null){
    			score = score + p.getCompatibility();
    		}
    		
    		
    		if(performanceService.getCategory(p.getOpe_fk()) == (long)24 || performanceService.getCategory(p.getOpe_fk()) == (long)25){
    			if(p.getCapacity() != null){
        			score = score + p.getCapacity();
        		}
    			
        		if(p.getSpecialty() != null){
        			score = score + p.getSpecialty();
        		}
    		}else{
    			if(p.getDiscipline() != null){
        			score = score + p.getDiscipline();
        		}
        		
        		if(p.getProfessional() != null){
        			score = score + p.getProfessional();
        		}
        		
        		if(p.getLearns() != null){
        			score = score + p.getLearns();
        		}
    		}
    		
    		p.setScore(score);
    		lcmPerformanceManager.save(p);
    	}
    	logger.info("Hello!");
    }
	
    @Transactional
    public void Calculate(String month){
    	List<Performance> list = hibernateInvoker.find(Performance.class,"from Performance p where p.month = '" + month + "'and p.factory like '%M%' and p.isValid is true");
    	for(Performance p : list){
    		double score = 0.0;
    		if(p.getAttendance() != null){
    			score = score + p.getAttendance();
    		}
    		if(p.getCompatibility() != null){
    			score = score + p.getCompatibility();
    		}
    		if(performanceService.getCategory(p.getOpe_fk()) == (long)24 || performanceService.getCategory(p.getOpe_fk()) == (long)25){
    			if(p.getCapacity() != null){
        			score = score + p.getCapacity();
        		}
    			
        		if(p.getSpecialty() != null){
        			score = score + p.getSpecialty();
        		}
    		}else{
    			if(p.getDiscipline() != null){
        			score = score + p.getDiscipline();
        		}
        		
        		if(p.getProfessional() != null){
        			score = score + p.getProfessional();
        		}
        		
        		if(p.getLearns() != null){
        			score = score + p.getLearns();
        		}
    		}
    		
    		p.setScore(score);
    		lcmPerformanceManager.save(p);
    	}
    	logger.info("Hello!");
    }
    
    
    @Transactional
    @Scheduled(cron = "0 05 10 16 * ? ")
    public void CalculateBonus(){
    	
    	String month = DateUtil.formatDate(new Date()).substring(0, 7);
    	List<Performance> list = hibernateInvoker.find(Performance.class,"from Performance p where p.month = '" + month + "'and p.factory like '%M%' and p.isValid is true");
    	for(Performance p : list){
    		double bonus = 0.0;
    		
    	
    		
    		if(p.getAttendance() != null){
    			bonus = bonus + p.getAttendance();
    		}
    		if(p.getCompatibility() != null){
    			bonus = bonus + p.getCompatibility();
    		}
    		
    		if(performanceService.getCategory(p.getOpe_fk()) == (long)24 || performanceService.getCategory(p.getOpe_fk()) == (long)25){
    			if(p.getCapacity() != null){
        			bonus = bonus + p.getCapacity();
        		}
        		if(p.getSpecialty() != null){
        			bonus = bonus + p.getSpecialty();
        		}
        		
    		}else{
    			if(p.getDiscipline() != null){
    				bonus = bonus + p.getDiscipline();
        		}
        		
        		if(p.getProfessional() != null){
        			bonus = bonus + p.getProfessional();
        		}
        		
        		if(p.getLearns() != null){
        			bonus = bonus + p.getLearns();
        		}
    		}
        		
        		
        		if(bonus < 60.0){
        			p.setBonus(0.0);
        		}else if(bonus >= 60.0 && bonus <= 61.0){
        			p.setBonus(10.0);
        		}else if(bonus >= 62.0 && bonus <= 63.0){
        			p.setBonus(20.0);
        		}else if(bonus >= 64.0 && bonus <= 65.0){
        			p.setBonus(30.0);
        		}else if(bonus >= 66.0 && bonus <= 67.0){
        			p.setBonus(40.0);
        		}else if(bonus >= 68.0 && bonus <= 69.0){
        			p.setBonus(50.0);
        		}else if(bonus == 70.0){
        			p.setBonus(51.0);
        		}else if(bonus >= 71.0 && bonus <= 72.0){
        			p.setBonus(60.0);
        		}else if(bonus >= 73.0 && bonus <= 74.0){
        			p.setBonus(70.0);
        		}else if(bonus >= 75.0 && bonus <= 76.0){
        			p.setBonus(80.0);
        		}else if(bonus >= 77.0 && bonus <= 78.0){
        			p.setBonus(90.0);
        		}else if(bonus >= 79.0 && bonus <= 80.0){
        			p.setBonus(100.0);
        		}else if(bonus >= 81.0 && bonus <= 82.0){
        			p.setBonus(110.0);
        		}else if(bonus >= 83.0 && bonus <= 84.0){
        			p.setBonus(140.0);
        		}else if(bonus >= 85.0 && bonus <= 86.0){
        			p.setBonus(160.0);
        		}else if(bonus >= 87.0 && bonus <= 88.0){
        			p.setBonus(180.0);
        		}else if(bonus >= 89.0 && bonus <= 90.0){
        			p.setBonus(200.0);
        		}else if(bonus >= 91.0 && bonus <= 92.0){
        			p.setBonus(210.0);
        		}else if(bonus >= 93.0 && bonus <= 94.0){
        			p.setBonus(240.0);
        		}else if(bonus >= 95.0 && bonus <= 96.0){
        			p.setBonus(260.0);
        		}else if(bonus >= 97.0 && bonus <= 98.0){
        			p.setBonus(280.0);
        		}else if(bonus >= 99.0 && bonus <= 100.0){
        			p.setBonus(300.0);
        		}
        		lcmPerformanceManager.save(p);
    		
    	
    	}
    	logger.info("Hello!");
    }
    
    
    @Transactional
    public void CalculateBonus(String month){
    	List<Performance> list = hibernateInvoker.find(Performance.class,"from Performance p where p.month = '" + month + "'and p.factory like '%M%' and p.isValid is true");
    	for(Performance p : list){
    		double bonus = 0.0;
    		if(p.getEmp_id().equals("C0910163")){
    			System.out.println("1");
    		}
    		if(p.getAttendance() != null){
    			bonus = bonus + p.getAttendance();
    		}
    		if(p.getCompatibility() != null){
    			bonus = bonus + p.getCompatibility();
    		}
    		
    		if(performanceService.getCategory(p.getOpe_fk()) == (long)24 || performanceService.getCategory(p.getOpe_fk()) == (long)25){
    			if(p.getCapacity() != null){
        			bonus = bonus + p.getCapacity();
        		}
        		if(p.getSpecialty() != null){
        			bonus = bonus + p.getSpecialty();
        		}
        		
    		}else{
    			if(p.getDiscipline() != null){
    				bonus = bonus + p.getDiscipline();
        		}
        		
        		if(p.getProfessional() != null){
        			bonus = bonus + p.getProfessional();
        		}
        		
        		if(p.getLearns() != null){
        			bonus = bonus + p.getLearns();
        		}
    		}
        		
        		if(bonus < 60.0){
        			p.setBonus(0.0);
        		}else if(bonus >= 60.0 && bonus <= 61.0){
        			p.setBonus(10.0);
        		}else if(bonus >= 62.0 && bonus <= 63.0){
        			p.setBonus(20.0);
        		}else if(bonus >= 64.0 && bonus <= 65.0){
        			p.setBonus(30.0);
        		}else if(bonus >= 66.0 && bonus <= 67.0){
        			p.setBonus(40.0);
        		}else if(bonus >= 68.0 && bonus <= 69.0){
        			p.setBonus(50.0);
        		}else if(bonus == 70.0){
        			p.setBonus(51.0);
        		}else if(bonus >= 71.0 && bonus <= 72.0){
        			p.setBonus(60.0);
        		}else if(bonus >= 73.0 && bonus <= 74.0){
        			p.setBonus(70.0);
        		}else if(bonus >= 75.0 && bonus <= 76.0){
        			p.setBonus(80.0);
        		}else if(bonus >= 77.0 && bonus <= 78.0){
        			p.setBonus(90.0);
        		}else if(bonus >= 79.0 && bonus <= 80.0){
        			p.setBonus(100.0);
        		}else if(bonus >= 81.0 && bonus <= 82.0){
        			p.setBonus(110.0);
        		}else if(bonus >= 83.0 && bonus <= 84.0){
        			p.setBonus(140.0);
        		}else if(bonus >= 85.0 && bonus <= 86.0){
        			p.setBonus(160.0);
        		}else if(bonus >= 87.0 && bonus <= 88.0){
        			p.setBonus(180.0);
        		}else if(bonus >= 89.0 && bonus <= 90.0){
        			p.setBonus(200.0);
        		}else if(bonus >= 91.0 && bonus <= 92.0){
        			p.setBonus(210.0);
        		}else if(bonus >= 93.0 && bonus <= 94.0){
        			p.setBonus(240.0);
        		}else if(bonus >= 95.0 && bonus <= 96.0){
        			p.setBonus(260.0);
        		}else if(bonus >= 97.0 && bonus <= 98.0){
        			p.setBonus(280.0);
        		}else if(bonus >= 99.0 && bonus <= 100.0){
        			p.setBonus(300.0);
        		}
        		lcmPerformanceManager.save(p);
    		
    	
    	}
    	logger.info("Hello!");
    }
    
    
	public double CalculateAttendance(PerformanceMon objPerformanceMon, String month){
		double attendance = 0.0;
		Double shfthour = objPerformanceMon.getShftHour();
		Double attdhour = objPerformanceMon.getAttdHour();
		Double prsnhour = objPerformanceMon.getPrsnHour();
		Double sickhour = objPerformanceMon.getSickHour();
		BigDecimal shfthour1 = new BigDecimal(shfthour);
		BigDecimal attdhour1 = new BigDecimal(attdhour);
		BigDecimal prsnhour1 = new BigDecimal(prsnhour);
		BigDecimal sickhour1 = new BigDecimal(sickhour);
		BigDecimal diffhour = shfthour1.subtract(attdhour1);//差异时数=应出勤-实际出勤
		BigDecimal sumhour = prsnhour1.subtract(sickhour1);//病假时数加事假时数
		Code co = hibernateInvoker.findUnique(Code.class, "from Code where id = " + objPerformanceMon.getOpe_fk() + " and isValid = true");
		
		if(performanceService.getCategory(objPerformanceMon.getOpe_fk()) == (long)24 || performanceService.getCategory(objPerformanceMon.getOpe_fk()) == (long)25){
			int i = diffhour.compareTo(BigDecimal.ZERO);  //i = 差异时数-0
			if(i<0){
				Double s= diffhour.divide(new BigDecimal(20), 0,BigDecimal.ROUND_HALF_UP).doubleValue();
				attendance = 5.0 + Math.abs(s);
			}
			else if (i>0){ 
				Double s= diffhour.divide(new BigDecimal(10), 0,BigDecimal.ROUND_HALF_UP).doubleValue();
				attendance = 5.0 - Math.abs(s);
			}
			else if (i==0){
				attendance = 5.0;
			}
			if(attendance>10) attendance=10.0;
			if(attendance<0)  attendance=0.0;
		}else{
			//25 - （病假时数+事假时数）/168H *25 
			Double s= sumhour.divide(new BigDecimal(168), 0,BigDecimal.ROUND_HALF_UP).doubleValue();
			attendance = 25 - s * 25;
			if(attendance>25) attendance=25.0;
			if(attendance<0)  attendance=0.0;
		}
		
		
		return attendance;
	}
	
	public double CalculateCapacity(PerformanceMon objPerformanceMon, double totalScore, String month){
		double capacity = 0.0;
		Double proportion = new Double(0.0);
		PerformanceMon p = hibernateInvoker.findUnique(PerformanceMon.class, "from PerformanceMon p where p.month = '"+ month + "' and p.emp_id = '" + objPerformanceMon.getEmp_id() + "'");
		Double output = objPerformanceMon.getOutput();
		Double cnlow = objPerformanceMon.getCnlow();
		if(output != null && cnlow != null && cnlow != 0.0){
			proportion = new BigDecimal(output).divide(new BigDecimal(cnlow), 2, BigDecimal.ROUND_DOWN).doubleValue();
		}
				
		if(proportion >= 1){
			capacity = totalScore;
		}else if(proportion < 1.00 && proportion >= 0.95){
			capacity = totalScore - 5.0;
		}else if(proportion < 0.95 && proportion >= 0.90){
			capacity = totalScore - 10.0;
		}else if(proportion < 0.90 && proportion >= 0.85){
			capacity = totalScore - 15.0;
		}else if(proportion < 0.85){
			capacity = 0.0;
		}
		return capacity;
	}
	
	public double CalculateQuality(PerformanceMon objPerformanceMon, double totalScore, String month){
		String from ="";
		String to = month + "-15";
		SimpleDateFormat sdf =  new SimpleDateFormat("yyyy-MM-dd");
		Calendar calendar = Calendar.getInstance(); 
		calendar.add(Calendar.MONTH, -1);   
		String str1 = sdf.format(calendar.getTime());
		from = str1.substring(0, 7) + "-16";
		List<PerformanceDay> performanceday = hibernateInvoker.find(PerformanceDay.class, "from PerformanceDay p where p.emp_id = '" + objPerformanceMon.getEmp_id() + "' and p.fab_date >= '" + from + "' and p.fab_date <= '" + to + "'");
		if(performanceday.size() == 0){
			return totalScore;
		}else{
			for(PerformanceDay per : performanceday){
				if(per.getType() == 31 || per.getType() == 32 || per.getType() == 33){
					return 0.0;
				}
			}
		}
		return 0.0;
	}
	
	public double CalculateDPPM(PerformanceMon objPerformanceMon, double totalScore, String month){
		List<PerformanceDay> performanceday = hibernateInvoker.find(PerformanceDay.class, "from PerformanceDay p where p.emp_id = '" + objPerformanceMon.getEmp_id() + "' and p.fab_date = '" + month + "' and p.type = '34'" );
		if(performanceday.size() == 0){
			return totalScore;
		}else{
			if(performanceday.size() == 1)return 5.0;
			if(performanceday.size() >= 1)return 0.0;
		}
		return 0.0;
	}
}
